package com.hancher.gamelife2.diary;

import static com.hancher.gamelife2.backup.BaiduNetManager.BAIDU_API_DOWNLOAD_MESSAGE;

import android.os.Bundle;
import android.text.Editable;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.navigation.Navigation;
import androidx.sqlite.db.SimpleSQLiteQuery;

import com.github.gzuliyujiang.wheelpicker.entity.DateEntity;
import com.haibin.calendarview.Calendar;
import com.haibin.calendarview.CalendarView;
import com.hancher.common.androidutil.AfterTextWatcher;
import com.hancher.common.androidutil.AsyncUtils;
import com.hancher.common.androidutil.FastClickUtil;
import com.hancher.common.androidutil.KeyEventUtil;
import com.hancher.common.androidutil.LogUtil;
import com.hancher.common.androidutil.MmkvUtil;
import com.hancher.common.androidutil.PageBean;
import com.hancher.common.androidutil.PathUtil;
import com.hancher.common.androidutil.ToastUtil;
import com.hancher.common.androidutil.UriUtil;
import com.hancher.common.base.BaseApplication;
import com.hancher.common.base.BaseMvpFragment;
import com.hancher.common.javautil.DateUtil;
import com.hancher.common.javautil.EmptyUtil;
import com.hancher.common.javautil.GsonUtil;
import com.hancher.common.net.download.DownloadListener;
import com.hancher.common.room.DbFiliter;
import com.hancher.common.rv.PageRecyclerViewManager;
import com.hancher.gamelife2.R;
import com.hancher.gamelife2.backup.BaiduNetApi;
import com.hancher.gamelife2.backup.BaiduNetManager;
import com.hancher.gamelife2.databinding.FragmentDiaryListBinding;
import com.hancher.gamelife2.home.HomePresenter;
import com.hancher.gamelife2.login.BaiduLoginFragment;
import com.hancher.gamelife2.main.MainDatabase_Impl;
import com.jeremyliao.liveeventbus.LiveEventBus;
import com.kevin.photo_browse.PhotoBrowse;
import com.kevin.photo_browse.ShowType;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.impl.LoadingPopupView;
import com.scwang.smart.refresh.layout.api.RefreshLayout;
import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.rxjava3.functions.Consumer;

/**
 * 作者 : Hancher ytu_shaoweijie@163.com <br/>
 * 时间 : 2023/3/12 0012 22:49 <br/>
 * 描述 :
 */
public class DiaryListFragment extends BaseMvpFragment<FragmentDiaryListBinding, HomePresenter> {


    private static final String DIARY_LIST_MONTH_FILTER = "DIARY_LIST_MONTH_FILTER";
    private static final String DIARY_LIST_YEAR = "DIARY_LIST_YEAR";
    private static final String DIARY_LIST_MONTH = "DIARY_LIST_MONTH";
    private static final String DIARY_LIST_DAY = "DIARY_LIST_DAY";
    private PageRecyclerViewManager<DiaryPO> prvm;
    DbFiliter filiter = new DbFiliter();
    /**
     * 数据缓存，等待获取图片地址后一起显示
     */
    PageBean<DiaryPO> loadingData = null;
    /**
     * 等待数据获取完成（数据+百度缩略图）
     */
    private LoadingPopupView waitDialog;

    @Override
    protected void initView(Bundle savedInstanceState) {
        prvm = new PageRecyclerViewManager<DiaryPO>()
                .setContext(getContext())
                .setRecyclerView(binding.recyclerview)
                .setRefreshLayout(binding.refreshLayout)
                .setEnableLoadMore(false)
                .setRefreshListener(new OnRefreshLoadMoreListener() {
                    @Override
                    public void onLoadMore(@NonNull RefreshLayout refreshLayout) {
                        queryDiaryList(PageRecyclerViewManager.LOADMORE);
                    }

                    @Override
                    public void onRefresh(@NonNull RefreshLayout refreshLayout) {
                        queryDiaryList(PageRecyclerViewManager.FRESH);
                    }
                })
                .setAdapter(new DiaryListAdapter((fistPosition, secondPosition) -> downAndShowImage(prvm.getRvList().get(fistPosition), secondPosition)))
                .addOnItemChildClickListener(R.id.img_del, (baseQuickAdapter, view, i) -> {
                    new XPopup.Builder(getContext()).asConfirm("删除记录", "确定删除此条记录?",
                                    () -> deleteDiaryItem(prvm.getRvList().get(i)))
                            .show();
                })
                .addOnItemChildClickListener(R.id.img_edit, (baseQuickAdapter, view, i) -> modifyDiary(prvm.getRvList().get(i)))
                .addOnItemChildClickListener(R.id.img1, (baseQuickAdapter, view, i) -> downAndShowImage(prvm.getRvList().get(i), 0))
                .addOnItemChildClickListener(R.id.img2, (baseQuickAdapter, view, i) -> downAndShowImage(prvm.getRvList().get(i), 0))
                .addOnItemChildClickListener(R.id.img3, (baseQuickAdapter, view, i) -> downAndShowImage(prvm.getRvList().get(i), 1))
                .setDivider(true)
                .init();


        binding.tvMonthFilter.setText(MmkvUtil.getString(DIARY_LIST_MONTH_FILTER, "月"));
        binding.calendarView.setVisibility(MmkvUtil.getString(DIARY_LIST_MONTH_FILTER, "月").equals("月") ? View.GONE : View.VISIBLE);

        int lastYear = MmkvUtil.getInt(DIARY_LIST_YEAR, DateUtil.getYear());
        int lastMonth = MmkvUtil.getInt(DIARY_LIST_MONTH, DateUtil.getMonth());
        int lastDay = MmkvUtil.getInt(DIARY_LIST_DAY, DateUtil.getDay());
        //请求参数
        filiter.setStart(DateUtil.getFirstStampOfMonth(lastYear, lastMonth, 0));
        filiter.setEnd(DateUtil.getFirstStampOfMonth(lastYear, lastMonth, 1));
        //日历
        binding.calendarView.setSelectEndCalendar(lastYear, lastMonth, lastDay);
        binding.calendarView.setSelectStartCalendar(lastYear, lastMonth, lastDay);
        binding.calendarView.setOnCalendarSelectListener(new CalendarView.OnCalendarSelectListener() {
            @Override
            public void onCalendarOutOfRange(Calendar calendar) {

            }

            @Override
            public void onCalendarSelect(Calendar calendar, boolean isClick) {
                MmkvUtil.put(DIARY_LIST_YEAR, calendar.getYear());
                MmkvUtil.put(DIARY_LIST_MONTH, calendar.getMonth());
                MmkvUtil.put(DIARY_LIST_DAY, calendar.getDay());
                updateListAfterDayMonthChange();
            }
        });
        binding.calendarView.setOnMonthChangeListener(this::updateListArterMonthChange);

        //滚动时间
        binding.dateWheelLayout.setRange(DateEntity.yearOnFuture(-50), DateEntity.yearOnFuture(1));
        binding.dateWheelLayout.setDefaultValue(DateEntity.target(lastYear, lastMonth, 0));
        binding.dateWheelLayout.setOnDateSelectedListener((year, month, day) -> updateListArterMonthChange(year, month));
    }


    @Override
    protected void initListener() {
        binding.imgEdit.setOnClickListener(v -> {
            Navigation.findNavController(binding.container).navigate(R.id.action_diaryListFragment_to_diaryEditFragment);
        });
//        binding.imgBackup.setOnClickListener(v -> {
//            Navigation.findNavController(binding.container).navigate(R.id.action_diaryListFragment_to_backupFragment);
//        });
        binding.tvMonthFilter.setOnClickListener(v -> {
            String str = binding.tvMonthFilter.getText().toString().equals("月") ? "日" : "月";
            binding.tvMonthFilter.setText(str);
            MmkvUtil.put(DIARY_LIST_MONTH_FILTER, str);
            binding.calendarView.setVisibility("日".equals(str) ? View.VISIBLE : View.GONE);
            updateListAfterDayMonthChange();
        });
        binding.etSearch.addTextChangedListener(new AfterTextWatcher() {
            @Override
            public void afterTextChanged(Editable s) {
                binding.imgClear.setVisibility(EmptyUtil.isNotEmpty(s.toString()) ? View.VISIBLE : View.GONE);
            }
        });
        binding.etSearch.setOnKeyListener((v, keyCode, event) -> {
            if (KeyEventUtil.isEnterUp(event) && !FastClickUtil.isQuick()) {
                queryDiaryList(PageRecyclerViewManager.FRESH);
                return true;
            }
            return false;
        });
        binding.imgClear.setOnClickListener(v -> {
            binding.etSearch.setText("");
            queryDiaryList(PageRecyclerViewManager.FRESH);
        });
        LiveEventBus.get(BAIDU_API_DOWNLOAD_MESSAGE, String.class)
                .observe(this, s -> {
                    if ("下载完成".equals(s)) {
                        cycleDown();
                    } else if (EmptyUtil.isNotEmpty(s) && s.startsWith("下载失败")) {
                        cycleDown();
                    }
                });
    }

    @Override
    protected void initData() {
        queryDiaryList(PageRecyclerViewManager.FRESH);
    }


    //region 查询数据

    /**
     * 月份切换，需要查询
     * @param year
     * @param month
     */
    private void updateListArterMonthChange(int year, int month) {
        int lastYear = MmkvUtil.getInt(DIARY_LIST_YEAR, DateUtil.getYear());
        int lastMonth = MmkvUtil.getInt(DIARY_LIST_MONTH, DateUtil.getMonth());
        if (year == lastYear && lastMonth == month) {
            return;
        }
        LogUtil.d("选中日期：" + year + "-" + month);

        filiter.setStart(DateUtil.getFirstStampOfMonth(year, month, 0));
        filiter.setEnd(DateUtil.getFirstStampOfMonth(year, month, 1));
        MmkvUtil.put(DIARY_LIST_YEAR, year);
        MmkvUtil.put(DIARY_LIST_MONTH, month);
        MmkvUtil.put(DIARY_LIST_DAY, 1);

        if (binding.dateWheelLayout.getSelectedYear() != year || binding.dateWheelLayout.getSelectedMonth() != month) {
            binding.dateWheelLayout.setDefaultValue(DateEntity.target(year, month, 0));
        }
        if (binding.calendarView.getSelectedCalendar().getYear() != year || binding.calendarView.getSelectedCalendar().getMonth() != month) {
            binding.calendarView.setSelectEndCalendar(year, month, 1);
            binding.calendarView.setSelectStartCalendar(year, month, 1);
            binding.calendarView.scrollToCalendar(year, month, 1);
        }

        queryDiaryList(PageRecyclerViewManager.FRESH);
    }

    /**
     * 查询
     * @param fresh
     */
    private void queryDiaryList(String fresh) {
//        prvm.setDataChangeType(fresh);
        waitDialog = (LoadingPopupView) new XPopup.Builder(getContext())
                .dismissOnBackPressed(false)
                .dismissOnTouchOutside(false)
                .asLoading("正在加载中")
                .show();
        AsyncUtils.run(emitter -> {
            StringBuffer sql = new StringBuffer();
            Object whereArgs = null;
            sql.append(" SELECT * FROM diary WHERE deleteflag!=1 ");
            if (EmptyUtil.isNotEmpty(binding.etSearch.getText().toString())) {
                sql.append(" AND content LIKE '%").append(binding.etSearch.getText().toString()).append("%' ");
            } else {
                sql.append(" AND createTime BETWEEN ").append(filiter.getStart()).append(" AND ").append(filiter.getEnd()).append(" ");
            }
            sql.append(" ORDER BY createTime DESC ");
//            if (EmptyUtil.isEmpty(binding.etSearch.getText().toString())) {
//                sql.append(" LIMIT ")
//                        .append((prvm.getPage() - 1) * prvm.getSize()).append(" , ")
//                        .append(prvm.getPage() * prvm.getSize()).append(" ");
//            }
            LogUtil.d("sql : " + sql);
            List<DiaryPO> data = MainDatabase_Impl.getInstance().diaryDao().getList(new SimpleSQLiteQuery(sql.toString()));

            int count;
            count = data.size();
//            if (EmptyUtil.isEmpty(binding.etSearch.getText().toString())) {
//                count = MainDatabase_Impl.getInstance().diaryDao().count();
//            } else {
//                count = data.size();
//            }

            emitter.onNext(new PageBean<>(data, count));
        }, (Consumer<PageBean<DiaryPO>>) data -> {
            LogUtil.d("数据库查询到数据：" + data.getCount());
            loadingData = data;
            if (EmptyUtil.isEmpty(loadingData.getData())) {
                prvm.freshData(new ArrayList<>());
                if (waitDialog != null && waitDialog.isShow()) {
                    waitDialog.dismiss();
                }
                return;
            }
//            prvm.freshPageData(data.getData(), data.getCount());
            if (waitDialog != null && waitDialog.isShow()) {
                waitDialog.setTitle("数据库查询成功，查到" + data.getCount() + "条");
            }
            queryThumb();
        });
    }

    /**
     * 日视图和月视图切换
     */
    private void updateListAfterDayMonthChange() {
        if ("月".equals(MmkvUtil.getString(DIARY_LIST_MONTH_FILTER, "月"))) {
            prvm.freshData(loadingData.getData());
        } else {
            int year = MmkvUtil.getInt(DIARY_LIST_YEAR, DateUtil.getYear());
            int month = MmkvUtil.getInt(DIARY_LIST_MONTH, DateUtil.getMonth());
            int day = MmkvUtil.getInt(DIARY_LIST_DAY, DateUtil.getDay());

            Long startStamp = DateUtil.getFirstStampOfDay(year, month, day, 0);
            Long endStamp = DateUtil.getFirstStampOfDay(year, month, day, 1);
            if (startStamp != null && endStamp != null) {
                List<DiaryPO> diaryPOS = new ArrayList<>();
                Map<String, Calendar> mSchemeDates = new HashMap<>();
                for (DiaryPO item : loadingData.getData()) {
                    if (item.getCreateTime() != null && item.getCreateTime() > startStamp && item.getCreateTime() < endStamp) {
                        diaryPOS.add(item);
                    }
                    Calendar calendar = new Calendar();
                    calendar.setYear(DateUtil.getYear(item.getCreateTime()));
                    calendar.setMonth(DateUtil.getMonth(item.getCreateTime()));
                    calendar.setDay(DateUtil.getDay(item.getCreateTime()));
                    calendar.setScheme("记 ");
                    mSchemeDates.put(calendar.toString(), calendar);
                }
                binding.calendarView.setSchemeDate(mSchemeDates);
                prvm.freshData(diaryPOS);
            } else {
                prvm.freshData(new ArrayList<>());
            }
        }
        binding.recyclerview.scrollToPosition(0);
    }
    //endregion

    //region 下载并预览
    LoadingPopupView downloadWaiting;

    private void downAndShowImage(DiaryPO diaryPO, int i) {
        try {
            List<String> fsidList = GsonUtil.str2ObjList(diaryPO.getFsids());
            List<String> imageList = GsonUtil.str2ObjList(diaryPO.getImages());
            if (EmptyUtil.isEmpty(fsidList)) {
                ToastUtil.show("预览失败，无fsid");
                return;
            }
            if (fsidList.size() <= i) {
                ToastUtil.show("未找到对应位置fsid");
                return;
            }
            File file = new File(PathUtil.OUT_APP_CACHE + imageList.get(i));
            if (file.exists()) {
                PhotoBrowse.with(getActivity())
                        .showType(ShowType.SINGLE_URI)
                        .uri(UriUtil.getUri(BaseApplication.getInstance().getApplicationContext(), file))
                        .show();
                return;
            }
            downloadWaiting = (LoadingPopupView) new XPopup.Builder(getContext())
                    .dismissOnTouchOutside(false)
                    .dismissOnBackPressed(false)
                    .asLoading("正在加载中")
                    .show();
            listDownFileInfo(Arrays.asList(fsidList.get(i)));

        } catch (Exception e) {
            LogUtil.e("err:", e);
        }
    }


    /**
     * 查询文件
     */
    public void listDownFileInfo(List<String> fsIds) {
        BaiduNetApi.ListInfoDTO resquest = new BaiduNetApi.ListInfoDTO()
                .setAccess_token(MmkvUtil.getString(BaiduLoginFragment.BAIDUNET_ACCESS_TOKEN, ""))
                .setFsids(fsIds);
        downloadWaiting.setTitle("开始查询");
        BaiduNetApi.listInfo(resquest).subscribe(listInfoVO -> {
            if (EmptyUtil.isEmpty(listInfoVO.getList())) {
                downloadWaiting.dismiss();
                ToastUtil.show("未找到百度文件");
                return;
            }
            downAndShowImage(listInfoVO.getList().get(0));
        }, throwable -> {
            downloadWaiting.dismiss();
            ToastUtil.show("查询百度文件信息失败");
            LogUtil.e(throwable);
        });
    }

    public void downAndShowImage(BaiduNetApi.ListInfoVO.Item item) {
        String newUrl = item.getDlink() + "&access_token=" + MmkvUtil.getString(BaiduLoginFragment.BAIDUNET_ACCESS_TOKEN, "");
        File file = new File(PathUtil.OUT_APP_CACHE + item.getPath());
        downloadWaiting.setTitle("开始下载图片,百度限速请稍后...");
        BaiduNetApi.download(newUrl, file.getAbsolutePath(), new DownloadListener() {
            @Override
            public void onStart() {
                downloadWaiting.setTitle("下载图片已开始");
            }

            @Override
            public void onProgress(int progress) {
                downloadWaiting.setTitle("图片下载进度+" + progress);
            }

            @Override
            public void onFinish(String path) {
                LogUtil.d("下载完成：" + path);
                downloadWaiting.dismiss();
                PhotoBrowse.with(getActivity())
                        .showType(ShowType.SINGLE_URI)
                        .uri(UriUtil.getUri(BaseApplication.getInstance().getApplicationContext(), file))
                        .show();
            }

            @Override
            public void onFail(String errorInfo) {
                downloadWaiting.dismiss();
                ToastUtil.show("下载失败：" + errorInfo);
            }
        });
    }
    //endregion

    //region 点击条目
    private void modifyDiary(DiaryPO diaryPO) {
        Bundle finalArgs = new Bundle();
        finalArgs.putString("data", diaryPO.getUuid());
        Navigation.findNavController(binding.container).navigate(R.id.action_diaryListFragment_to_diaryEditFragment, finalArgs);
    }

    private void deleteDiaryItem(DiaryPO diaryPO) {
        AsyncUtils.run(emitter -> {
            diaryPO.setUpdateTime(System.currentTimeMillis());
            diaryPO.setDeleteflag((byte) 1);
            MainDatabase_Impl.getInstance().diaryDao().updateItem(diaryPO);
            emitter.onNext("");
        }, data -> {
            queryDiaryList(PageRecyclerViewManager.FRESH);
        });
    }

    //endregion

    //region 获取缩略图
    List<String> thumbs = new ArrayList<>();

    private void queryThumb() {
        thumbs.clear();
        if (loadingData == null || EmptyUtil.isEmpty(loadingData.getData())) {
            if (waitDialog != null && waitDialog.isShow()) {
                waitDialog.dismiss();
            }
            return;
        }
        for (DiaryPO diaryPO : loadingData.getData()) {
            if (EmptyUtil.isEmpty(diaryPO.getFsids())) {
                continue;
            }
            try {
                List<String> images = GsonUtil.str2ObjList(diaryPO.getFsids());
                thumbs.addAll(images);
            } catch (Exception e) {
                LogUtil.e("err:", e);
            }
        }
        if (waitDialog != null && waitDialog.isShow()) {
            waitDialog.setTitle(String.format("查询到%d数据，%d图，缩略图查询开始", loadingData.getCount(), thumbs.size()));
        }
        listInfo(thumbs);
    }

    /**
     * 查询文件
     */
    public void listInfo(List<String> fsIds) {
        BaiduNetApi.ListInfoDTO resquest = new BaiduNetApi.ListInfoDTO()
                .setAccess_token(MmkvUtil.getString(BaiduLoginFragment.BAIDUNET_ACCESS_TOKEN, ""))
                .setFsids(fsIds);
        BaiduNetApi.listInfo(resquest).subscribe(listInfoVO -> {
            if (EmptyUtil.isEmpty(listInfoVO.getList())) {
                if (waitDialog != null && waitDialog.isShow()) {
                    waitDialog.dismiss();
                }
                prvm.freshData(loadingData.getData());
                return;
            }
            //将结果映射到diary数组中
            HashMap<String, String> fsidUrlMap = new HashMap<>();
            for (BaiduNetApi.ListInfoVO.Item item : listInfoVO.getList()) {
                if (item.getThumbs() == null) {
                    continue;
                }
                if (EmptyUtil.isNotEmpty(item.getThumbs().getUrl4())) {
                    fsidUrlMap.put(item.getFs_id(), item.getThumbs().getUrl4());
                } else if (EmptyUtil.isNotEmpty(item.getThumbs().getUrl3())) {
                    fsidUrlMap.put(item.getFs_id(), item.getThumbs().getUrl3());
                } else if (EmptyUtil.isNotEmpty(item.getThumbs().getUrl2())) {
                    fsidUrlMap.put(item.getFs_id(), item.getThumbs().getUrl2());
                } else if (EmptyUtil.isNotEmpty(item.getThumbs().getUrl1())) {
                    fsidUrlMap.put(item.getFs_id(), item.getThumbs().getUrl1());
                } else if (EmptyUtil.isNotEmpty(item.getThumbs().getIcon())) {
                    fsidUrlMap.put(item.getFs_id(), item.getThumbs().getIcon());
                }
            }
            for (DiaryPO diaryPO : loadingData.getData()) {
                if (EmptyUtil.isEmpty(diaryPO.getFsids())) {
                    continue;
                }
                List<String> images = GsonUtil.str2ObjList(diaryPO.getFsids());
                List<String> urls = new ArrayList<>();
                for (String imageFsId : images) {
                    if (EmptyUtil.isEmpty(images)) {
                        continue;
                    }
                    urls.add(fsidUrlMap.get(imageFsId));
                }
                diaryPO.setImgUrls(urls);
            }
            if (waitDialog != null && waitDialog.isShow()) {
                waitDialog.dismiss();
                LogUtil.d("缩略图加载完成");
            }
            updateListAfterDayMonthChange();

        }, LogUtil::e);
    }

    //endregion

    //region 下载
    private int downIndex = 0;
    List<String> downFile = new ArrayList<>();

    private void checkAndDownPic() {
        downIndex = 0;
        downFile.clear();
        for (DiaryPO diaryPO : prvm.getRvList()) {
            if (EmptyUtil.isEmpty(diaryPO.getImages())) {
                continue;
            }
            try {
                List<String> images = GsonUtil.str2ObjList(diaryPO.getImages());
                downFile.addAll(images);
            } catch (Exception e) {
                LogUtil.e("err:", e);
            }
        }
        for (String item : downFile) {
            if (!(new File(PathUtil.OUT_APP_CACHE + item).exists())) {
                cycleDown();
                break;
            }
        }
    }

    private void cycleDown() {
        if (downIndex >= downFile.size()) {
            if (EmptyUtil.isNotEmpty(downFile)) {
                prvm.freshData();
            }
            return;
        }
        String item = downFile.get(downIndex);
        downIndex++;
        if (new File(PathUtil.OUT_APP_CACHE + item).exists()) {
            cycleDown();
        }
        BaiduNetManager.getInstance().downloadFile(item, PathUtil.OUT_APP_CACHE + item);
    }
    //endregion
}